{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3plmEok3ExZR"
      },
      "source": [
        "# Product Price Prediction: Fine-Tuning GPT-4o-mini to Beat $76 Baseline Error\n",
        "\n",
        "## Project Description\n",
        "\n",
        "This project fine-tunes OpenAI's GPT-4o-mini model to predict product prices based solely on product descriptions. The goal is to improve upon the baseline mean absolute error of $76 by training the model to estimate prices from textual product information including specifications, features, and descriptions.\n",
        "\n",
        "** What I did Differently ** \n",
        "- I used a specially curated open source subset of the Amazon Review Dataset to train the model\n",
        "\n",
        "The dataset used for this project is the **Amazon Product Price Prediction Dataset** curated specifically for LLM fine-tuning by Jai Keshav Sharma (2024). This dataset contains 400,000 Amazon product listings with detailed descriptions and corresponding prices, making it ideal for training language models on price estimation tasks.\n",
        "\n",
        "### Dataset Citation\n",
        "```\n",
        "@dataset{sharma2024amazon_price_prediction,\n",
        "  title={Amazon Product Price Prediction Dataset: Curated for LLM Fine-tuning},\n",
        "  author={Jai Keshav Sharma},\n",
        "  year={2024},\n",
        "  publisher={Hugging Face},\n",
        "  url={https://huggingface.co/datasets/ksharma9719/Amazon-Reviews-2023-curated_for_price_prediction}\n",
        "}\n",
        "```\n",
        "\n",
        "The model is trained to output price estimates in a standardized format, enabling e-commerce applications such as automated pricing, market analysis, and competitive intelligence.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Hst-keo-WWlf"
      },
      "source": [
        "Project Description:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "D9gjGvJX8oze"
      },
      "outputs": [],
      "source": [
        "# imports\n",
        "\n",
        "import os\n",
        "import re\n",
        "from google.colab import userdata\n",
        "import json\n",
        "from dotenv import load_dotenv\n",
        "from huggingface_hub import login\n",
        "from datasets import load_dataset\n",
        "import matplotlib.pyplot as plt\n",
        "from collections import Counter, defaultdict\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "from openai import OpenAI\n",
        "from typing import Optional\n",
        "import re\n",
        "from datasets import load_dataset\n",
        "import random\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "PMh_o7wRF9BK"
      },
      "outputs": [],
      "source": [
        "hf_token = userdata.get('HF_TOKEN')\n",
        "openai_api_key = userdata.get('OPENAI_API_KEY')\n",
        "\n",
        "login(hf_token, add_to_git_credential=True)\n",
        "openai = OpenAI(api_key=openai_api_key)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 113,
          "referenced_widgets": [
            "7310470b4a064a44b136f70054041618",
            "41482711593a4c28beec209690300478",
            "f6d3e158b3d043a884d8c19510a0dfc4",
            "b521eab4d01a4993b3be35ea66d12811",
            "7807f509779f4f2d891de798ffc1476c",
            "5411e5e9e393488dbeb2a255da336180",
            "e4f79de41af545be8faad495aeefa2bd",
            "2d441fd6a41944fc90190dac589a1131",
            "4efc837f649847a1b8a6c651cfcaf7fe",
            "02cbae7ae9674de08b58989185c31678",
            "e11a725a01ca4092a30e93a9be5d8237",
            "59a3948488c54d5b8f62111ac1f4fe6b",
            "5c2681fe88f94c8b9040d7c852066c71",
            "eb50ffb13e99429f9f97eaab1fd3a518",
            "7db75a41217947d8baaad1bae70c3e94",
            "d9b2ae0cf0564dbcac954be0a0fd82e9",
            "824ac35608b64ee18b2ac4120a141c7a",
            "5c846b08710b47a6bb290952faff7beb",
            "4e10820a60454823abcbfc98c8f6dc05",
            "b4fd2590613542dfa4094a7a0641f939",
            "8ede9aef6a6a4f5d837bf205f3cba707",
            "28dd05003dcf42c5b2bae63f8cdeb709",
            "8a26d6ea6e90444ab201ce610c6f6375",
            "17501e8dcca847dc9a741c79363423a3",
            "bc6d06024ffd4d359ac58786ef7567d1",
            "6907060854534820ab8c58653c9995f5",
            "ca274208b30846d6b7938c0124fcdfa3",
            "c447f3a3f833421499aba5b8c6e1c3d0",
            "c91a04c8314f4850abbaa051eabfb529",
            "a9b37dc49c39414897b8472b4da8d384",
            "38516c43b95f423a8b16dd98f60201b1",
            "ba214b2fd4f647669cfbe5086fb60d63",
            "6b376c825b664e248b9b52aaa022afbb"
          ]
        },
        "id": "6jM-39pw81ub",
        "outputId": "a931e235-2b02-42f1-a93d-18f215742957"
      },
      "outputs": [],
      "source": [
        "# This is the specially curated dataset from ksharrma\n",
        "dataset = load_dataset(\n",
        "    \"ksharma9719/Amazon-Reviews-2023-curated_for_price_prediction\",\n",
        "    data_files=\"data/train-00000-of-00001.parquet\"\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "rcvgtV1w_XQ3"
      },
      "outputs": [],
      "source": [
        "# Access the training data, and dividing it into train and test data\n",
        "total_length = len(dataset[\"train\"])\n",
        "\n",
        "# Shuffle indices\n",
        "all_indices = list(range(total_length))\n",
        "random.seed(42)\n",
        "random.shuffle(all_indices)\n",
        "\n",
        "train_indices = all_indices[:-2000]\n",
        "test_indices = all_indices[-2000:]\n",
        "\n",
        "train_data = dataset[\"train\"].select(train_indices)\n",
        "test_data = dataset[\"train\"].select(test_indices)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "cIsBDDewCW5T",
        "outputId": "3349341e-9d61-4033-f15a-4760f513c9c3"
      },
      "outputs": [],
      "source": [
        "print(f\"Total entries: {total_length}\")\n",
        "print(f\"Training entries: {len(train_data)}\")\n",
        "print(f\"Test entries: {len(test_data)}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "UlssOY6oPYwj"
      },
      "outputs": [],
      "source": [
        "# OpenAI recommends fine-tuning with populations of 50-100 examples\n",
        "# But as our examples are very small, I'm suggesting we go with 200 examples (and 1 epoch)\n",
        "\n",
        "fine_tune_train = train_data.select(range(200))\n",
        "fine_tune_validation = train_data.select(range(200,250))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NALlYuKMPgxs"
      },
      "source": [
        "## Preparing the data for Fine Tuning Using JSONL"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Nlhgv_nwPe4h"
      },
      "outputs": [],
      "source": [
        "# This function thoroughly formats the price data to make sure that there is no data leak into the training model\n",
        "def messages_for(item):\n",
        "    system_message = \"You are a price estimation assistant. Respond only with the estimated price in the format: Price is $X.XX\"\n",
        "    \n",
        "    user_prompt = item[\"text\"]\n",
        "    price = item[\"price\"]\n",
        "\n",
        "    user_prompt = user_prompt.replace(\" to the nearest dollar\", \"\")\n",
        "    user_prompt = user_prompt.replace(\"\\n\\nPrice is $\", \"\")\n",
        "    \n",
        "    price_formats = [\n",
        "        f\"{price:.2f}\",           \n",
        "        f\"{price:.0f}\",           \n",
        "        f\"{price}\",               \n",
        "        f\"{int(price)}\",          \n",
        "        f\"{price:.2f}\".replace('.', ''),  \n",
        "    ]\n",
        "    \n",
        "    for price_str in price_formats:\n",
        "        if user_prompt.endswith(price_str):\n",
        "            user_prompt = user_prompt[:-len(price_str)].strip()\n",
        "            break\n",
        "        if f\"${price_str}\" in user_prompt:\n",
        "            user_prompt = user_prompt.replace(f\"${price_str}\", \"\").strip()\n",
        "        if user_prompt.rstrip().endswith(price_str):\n",
        "            user_prompt = user_prompt.rstrip()[:-len(price_str)].strip()\n",
        "\n",
        "    user_prompt = re.sub(r'(\\d+\\.?\\d{0,2})$', '', user_prompt).strip()\n",
        "    \n",
        "    user_prompt = re.sub(r'\\$\\s*[\\d,]+\\.?\\d{0,2}', '', user_prompt)\n",
        "\n",
        "    if re.search(rf'\\b{int(price)}\\b\\s*$', user_prompt):\n",
        "        user_prompt = re.sub(rf'\\b{int(price)}\\b\\s*$', '', user_prompt).strip()\n",
        "    \n",
        "    return [\n",
        "        {\"role\": \"system\", \"content\": system_message},\n",
        "        {\"role\": \"user\", \"content\": user_prompt.strip()},\n",
        "        {\"role\": \"assistant\", \"content\": f\"Price is ${item['price']:.2f}\"}\n",
        "    ]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "vwZgVsTHP1Kl",
        "outputId": "97bc2bfe-ed65-4465-ffc4-c269eed96108"
      },
      "outputs": [],
      "source": [
        "messages_for(train_data[0])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "V4wuKvLZQxDx"
      },
      "outputs": [],
      "source": [
        "# Convert the items into a list of json objects - a \"jsonl\" string\n",
        "# Each row represents a message in the form:\n",
        "# {\"messages\" : [{\"role\": \"system\", \"content\": \"You estimate prices...\n",
        "\n",
        "def make_jsonl(items):\n",
        "    lines = []\n",
        "    for item in items:\n",
        "        messages = messages_for(item)\n",
        "        json_obj = {\"messages\": messages}\n",
        "        lines.append(json.dumps(json_obj))\n",
        "    return '\\n'.join(lines)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "0xP5tMiyQ2le",
        "outputId": "1cf0b37f-001a-4487-b8c0-e4ce291d63c8"
      },
      "outputs": [],
      "source": [
        "print(make_jsonl(train_data.select(range(3))))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "t2_q5hiNStKX"
      },
      "outputs": [],
      "source": [
        "\n",
        "def write_jsonl(items, filename):\n",
        "    with open(filename, \"w\") as f:\n",
        "        jsonl = make_jsonl(items)\n",
        "        f.write(jsonl)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kqhKyb9fS4ny"
      },
      "outputs": [],
      "source": [
        "write_jsonl(fine_tune_train, \"fine_tune_train.jsonl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZKpVJrlwUO3Z"
      },
      "outputs": [],
      "source": [
        "write_jsonl(fine_tune_validation, \"fine_tune_validation.jsonl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ES82SYR1Ug9e"
      },
      "outputs": [],
      "source": [
        "with open(\"fine_tune_train.jsonl\", \"rb\") as f:\n",
        "    train_file = openai.files.create(file=f, purpose=\"fine-tune\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "-oygMJ7GV_cu",
        "outputId": "be56458b-938c-488b-abb6-d48cca56b466"
      },
      "outputs": [],
      "source": [
        "train_file"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "owDVG0HtWCP-"
      },
      "outputs": [],
      "source": [
        "with open(\"fine_tune_validation.jsonl\", \"rb\") as f:\n",
        "    validation_file = openai.files.create(file=f, purpose=\"fine-tune\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "gt4BtFEiWEcx",
        "outputId": "2dd875e6-106c-4fe7-a33a-55ce55320ab7"
      },
      "outputs": [],
      "source": [
        "validation_file"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "j5U9HVFFXSgF"
      },
      "outputs": [],
      "source": [
        "wandb_integration = {\"type\": \"wandb\", \"wandb\": {\"project\": \"gpt-pricer\"}}"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "PZvKoAydXWOk",
        "outputId": "5c2c9df0-b63c-45ed-d33c-5e311292d9b2"
      },
      "outputs": [],
      "source": [
        "openai.fine_tuning.jobs.create(\n",
        "    training_file=train_file.id,\n",
        "    validation_file=validation_file.id,\n",
        "    model=\"gpt-4o-mini-2024-07-18\",\n",
        "    seed=42,\n",
        "    hyperparameters={\"n_epochs\": 1},\n",
        "    integrations = [wandb_integration],\n",
        "    suffix=\"pricer\"\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "GgQXC6q5Xx4a",
        "outputId": "1c2f7a6e-daeb-4633-c747-8385fe124709"
      },
      "outputs": [],
      "source": [
        "# job_id = openai.fine_tuning.jobs.list(limit=1).data[0].id\n",
        "job_id=\"ftjob-kMWRKdN9t8H0lDAxzHT5kmeB\"\n",
        "print(job_id)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "jZskxChzXtO8",
        "outputId": "b982bc19-2b68-4838-ae1d-9133065d721f"
      },
      "outputs": [],
      "source": [
        "openai.fine_tuning.jobs.retrieve(job_id)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "yqwIWxmiYRs3",
        "outputId": "f0e02411-06f5-496e-fb0c-6c8bfffa918f"
      },
      "outputs": [],
      "source": [
        "fine_tuned_model_name = openai.fine_tuning.jobs.retrieve(job_id).fine_tuned_model\n",
        "print(fine_tuned_model_name)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "d2dkrZlKYWCI"
      },
      "outputs": [],
      "source": [
        "# Try this out\n",
        "\n",
        "\n",
        "def messages_for(item):\n",
        "    system_message = \"You are a price estimation assistant. Respond only with the estimated price in the format: Price is $X.XX\"\n",
        "    \n",
        "    user_prompt = item[\"text\"]\n",
        "    price = item[\"price\"]\n",
        "    \n",
        "    # Remove common price-related phrases\n",
        "    user_prompt = user_prompt.replace(\" to the nearest dollar\", \"\")\n",
        "    user_prompt = user_prompt.replace(\"\\n\\nPrice is $\", \"\")\n",
        "    \n",
        "    # Create multiple price format variations to remove\n",
        "    price_formats = [\n",
        "        f\"{price:.2f}\",           # 329.00\n",
        "        f\"{price:.0f}\",           # 329\n",
        "        f\"{price}\",               # 329.0\n",
        "        f\"{int(price)}\",          # 329\n",
        "        f\"{price:.2f}\".replace('.', ''),  # 32900\n",
        "    ]\n",
        "    \n",
        "    # Try to remove each format from the end of the string\n",
        "    for price_str in price_formats:\n",
        "        # Remove from end (most common)\n",
        "        if user_prompt.endswith(price_str):\n",
        "            user_prompt = user_prompt[:-len(price_str)].strip()\n",
        "            break\n",
        "        # Remove with $ prefix\n",
        "        if f\"${price_str}\" in user_prompt:\n",
        "            user_prompt = user_prompt.replace(f\"${price_str}\", \"\").strip()\n",
        "        # Remove standalone number at the end\n",
        "        if user_prompt.rstrip().endswith(price_str):\n",
        "            user_prompt = user_prompt.rstrip()[:-len(price_str)].strip()\n",
        "    \n",
        "    # Additional regex cleanup - remove any trailing number that might be a price\n",
        "    # This catches cases where the price is stuck to the end of a word\n",
        "    user_prompt = re.sub(r'(\\d+\\.?\\d{0,2})$', '', user_prompt).strip()\n",
        "    \n",
        "    # Remove $ signs followed by numbers anywhere in the text\n",
        "    user_prompt = re.sub(r'\\$\\s*[\\d,]+\\.?\\d{0,2}', '', user_prompt)\n",
        "    \n",
        "    # Final safety check - if the price (as int) appears at the very end, remove it\n",
        "    if re.search(rf'\\b{int(price)}\\b\\s*$', user_prompt):\n",
        "        user_prompt = re.sub(rf'\\b{int(price)}\\b\\s*$', '', user_prompt).strip()\n",
        "    \n",
        "    return [\n",
        "        {\"role\": \"system\", \"content\": system_message},\n",
        "        {\"role\": \"user\", \"content\": user_prompt.strip()},\n",
        "        {\"role\": \"assistant\", \"content\": f\"Price is ${item['price']:.2f}\"}\n",
        "    ]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "lwoQbNSeYY1S"
      },
      "outputs": [],
      "source": [
        "\n",
        "def get_price(s):\n",
        "    s = s.replace('$','').replace(',','')\n",
        "    match = re.search(r\"[-+]?\\d*\\.\\d+|\\d+\", s)\n",
        "    return float(match.group()) if match else 0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "GN59aWE2YmD6",
        "outputId": "109afd7f-1b91-4a59-fce3-0fdaed14ea39"
      },
      "outputs": [],
      "source": [
        "get_price(\"The price is roughly $99.99 because blah blah\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "FDm8z8LXYquQ"
      },
      "outputs": [],
      "source": [
        "# The function for gpt-4o-mini\n",
        "\n",
        "def gpt_fine_tuned(item):\n",
        "    response = openai.chat.completions.create(\n",
        "        model=fine_tuned_model_name,\n",
        "        messages=messages_for(item),\n",
        "        seed=42,\n",
        "        max_tokens=7\n",
        "    )\n",
        "    reply = response.choices[0].message.content\n",
        "    return get_price(reply)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "OWGEt6ZUYsop",
        "outputId": "56a4dade-eafa-4128-fa16-52ef0252bad6"
      },
      "outputs": [],
      "source": [
        "item = test_data.select([0])[0]  # Select returns a dataset, so index [0] to get the item\n",
        "print(item[\"price\"])\n",
        "print(gpt_fine_tuned(item))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "2Hiov1XUMVB3"
      },
      "outputs": [],
      "source": [
        "import math\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "GREEN = \"\\033[92m\"\n",
        "BLUE = \"\\033[94m\"\n",
        "YELLOW = \"\\033[93m\"\n",
        "RED = \"\\033[91m\"\n",
        "RESET = \"\\033[0m\"\n",
        "COLOR_MAP = {\"red\":RED, \"orange\": YELLOW, \"green\": GREEN, \"blue\":BLUE}\n",
        "\n",
        "class Tester:\n",
        "\n",
        "    def __init__(self, predictor, data, title=None, size=250):\n",
        "        self.predictor = predictor\n",
        "        self.data = data\n",
        "        self.title = title or predictor.__name__.replace(\"_\", \" \").title()\n",
        "        self.size = size\n",
        "        self.guesses = []\n",
        "        self.truths = []\n",
        "        self.errors = []\n",
        "        self.sles = []\n",
        "        self.colors = []\n",
        "\n",
        "    def color_for(self, error, truth):\n",
        "        if error<40 or error/truth < 0.2:\n",
        "            return \"blue\"\n",
        "        elif error<80 or error/truth < 0.4:\n",
        "            return \"orange\"\n",
        "        else:\n",
        "            return \"red\"\n",
        "\n",
        "    def run_datapoint(self, i):\n",
        "        datapoint = self.data[i]\n",
        "        guess = self.predictor(datapoint)\n",
        "        truth = datapoint[\"price\"]\n",
        "        error = abs(guess - truth)\n",
        "        log_error = math.log(truth+1) - math.log(guess+1)\n",
        "        sle = log_error ** 2\n",
        "        color = self.color_for(error, truth)\n",
        "        title = datapoint[\"text\"] if len(datapoint[\"text\"]) <= 40 else datapoint[\"text\"][:40]+\"...\"\n",
        "        self.guesses.append(guess)\n",
        "        self.truths.append(truth)\n",
        "        self.errors.append(error)\n",
        "        self.sles.append(sle)\n",
        "        self.colors.append(color)\n",
        "        print(f\"{COLOR_MAP[color]}{i+1}: Guess: ${guess:,.2f} Truth: ${truth:,.2f} Error: ${error:,.2f} SLE: {sle:,.2f} Item: {title}{RESET}\")\n",
        "\n",
        "    def chart(self, title):\n",
        "        max_error = max(self.errors)\n",
        "        plt.figure(figsize=(12, 8))\n",
        "        max_val = max(max(self.truths), max(self.guesses))\n",
        "        plt.plot([0, max_val], [0, max_val], color='deepskyblue', lw=2, alpha=0.6)\n",
        "        plt.scatter(self.truths, self.guesses, s=3, c=self.colors)\n",
        "        plt.xlabel('Ground Truth')\n",
        "        plt.ylabel('Model Estimate')\n",
        "        plt.xlim(0, max_val)\n",
        "        plt.ylim(0, max_val)\n",
        "        plt.title(title)\n",
        "        plt.show()\n",
        "\n",
        "    def report(self):\n",
        "        average_error = sum(self.errors) / self.size\n",
        "        rmsle = math.sqrt(sum(self.sles) / self.size)\n",
        "        hits = sum(1 for color in self.colors if color==\"blue\")\n",
        "        title = f\"{self.title} Error=${average_error:,.2f} RMSLE={rmsle:,.2f} Hits={hits/self.size*100:.1f}%\"\n",
        "        self.chart(title)\n",
        "\n",
        "    def run(self):\n",
        "        self.error = 0\n",
        "        for i in range(self.size):\n",
        "            self.run_datapoint(i)\n",
        "        self.report()\n",
        "\n",
        "    @classmethod\n",
        "    def test(cls, function, data):\n",
        "        cls(function, data).run()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000
        },
        "id": "JGUWcFLrMcKX",
        "outputId": "0abdfee8-f379-4508-af0d-d27a6410f2f1"
      },
      "outputs": [],
      "source": [
        "Tester.test(gpt_fine_tuned, test_data)"
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "gpuType": "T4",
      "provenance": []
    },
    "kernelspec": {
      "display_name": "base",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3.12.4"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "02cbae7ae9674de08b58989185c31678": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "17501e8dcca847dc9a741c79363423a3": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_c447f3a3f833421499aba5b8c6e1c3d0",
            "placeholder": "​",
            "style": "IPY_MODEL_c91a04c8314f4850abbaa051eabfb529",
            "value": "Generating train split: "
          }
        },
        "28dd05003dcf42c5b2bae63f8cdeb709": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "2d441fd6a41944fc90190dac589a1131": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": "20px"
          }
        },
        "38516c43b95f423a8b16dd98f60201b1": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "ProgressStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "41482711593a4c28beec209690300478": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_5411e5e9e393488dbeb2a255da336180",
            "placeholder": "​",
            "style": "IPY_MODEL_e4f79de41af545be8faad495aeefa2bd",
            "value": "README.md: "
          }
        },
        "4e10820a60454823abcbfc98c8f6dc05": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "4efc837f649847a1b8a6c651cfcaf7fe": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "ProgressStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "5411e5e9e393488dbeb2a255da336180": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "59a3948488c54d5b8f62111ac1f4fe6b": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HBoxModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_5c2681fe88f94c8b9040d7c852066c71",
              "IPY_MODEL_eb50ffb13e99429f9f97eaab1fd3a518",
              "IPY_MODEL_7db75a41217947d8baaad1bae70c3e94"
            ],
            "layout": "IPY_MODEL_d9b2ae0cf0564dbcac954be0a0fd82e9"
          }
        },
        "5c2681fe88f94c8b9040d7c852066c71": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_824ac35608b64ee18b2ac4120a141c7a",
            "placeholder": "​",
            "style": "IPY_MODEL_5c846b08710b47a6bb290952faff7beb",
            "value": "data/train-00000-of-00001.parquet: 100%"
          }
        },
        "5c846b08710b47a6bb290952faff7beb": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "6907060854534820ab8c58653c9995f5": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_ba214b2fd4f647669cfbe5086fb60d63",
            "placeholder": "​",
            "style": "IPY_MODEL_6b376c825b664e248b9b52aaa022afbb",
            "value": " 400000/0 [00:04&lt;00:00, 117453.23 examples/s]"
          }
        },
        "6b376c825b664e248b9b52aaa022afbb": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "7310470b4a064a44b136f70054041618": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HBoxModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_41482711593a4c28beec209690300478",
              "IPY_MODEL_f6d3e158b3d043a884d8c19510a0dfc4",
              "IPY_MODEL_b521eab4d01a4993b3be35ea66d12811"
            ],
            "layout": "IPY_MODEL_7807f509779f4f2d891de798ffc1476c"
          }
        },
        "7807f509779f4f2d891de798ffc1476c": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "7db75a41217947d8baaad1bae70c3e94": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_8ede9aef6a6a4f5d837bf205f3cba707",
            "placeholder": "​",
            "style": "IPY_MODEL_28dd05003dcf42c5b2bae63f8cdeb709",
            "value": " 187M/187M [00:08&lt;00:00, 32.5MB/s]"
          }
        },
        "824ac35608b64ee18b2ac4120a141c7a": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "8a26d6ea6e90444ab201ce610c6f6375": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HBoxModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_17501e8dcca847dc9a741c79363423a3",
              "IPY_MODEL_bc6d06024ffd4d359ac58786ef7567d1",
              "IPY_MODEL_6907060854534820ab8c58653c9995f5"
            ],
            "layout": "IPY_MODEL_ca274208b30846d6b7938c0124fcdfa3"
          }
        },
        "8ede9aef6a6a4f5d837bf205f3cba707": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "a9b37dc49c39414897b8472b4da8d384": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": "20px"
          }
        },
        "b4fd2590613542dfa4094a7a0641f939": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "ProgressStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "b521eab4d01a4993b3be35ea66d12811": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "HTMLModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_02cbae7ae9674de08b58989185c31678",
            "placeholder": "​",
            "style": "IPY_MODEL_e11a725a01ca4092a30e93a9be5d8237",
            "value": " 10.2k/? [00:00&lt;00:00, 938kB/s]"
          }
        },
        "ba214b2fd4f647669cfbe5086fb60d63": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "bc6d06024ffd4d359ac58786ef7567d1": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "FloatProgressModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_a9b37dc49c39414897b8472b4da8d384",
            "max": 1,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_38516c43b95f423a8b16dd98f60201b1",
            "value": 1
          }
        },
        "c447f3a3f833421499aba5b8c6e1c3d0": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "c91a04c8314f4850abbaa051eabfb529": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "ca274208b30846d6b7938c0124fcdfa3": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "d9b2ae0cf0564dbcac954be0a0fd82e9": {
          "model_module": "@jupyter-widgets/base",
          "model_module_version": "1.2.0",
          "model_name": "LayoutModel",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "e11a725a01ca4092a30e93a9be5d8237": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "e4f79de41af545be8faad495aeefa2bd": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "eb50ffb13e99429f9f97eaab1fd3a518": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "FloatProgressModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_4e10820a60454823abcbfc98c8f6dc05",
            "max": 186628937,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_b4fd2590613542dfa4094a7a0641f939",
            "value": 186628937
          }
        },
        "f6d3e158b3d043a884d8c19510a0dfc4": {
          "model_module": "@jupyter-widgets/controls",
          "model_module_version": "1.5.0",
          "model_name": "FloatProgressModel",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_2d441fd6a41944fc90190dac589a1131",
            "max": 1,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_4efc837f649847a1b8a6c651cfcaf7fe",
            "value": 1
          }
        }
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
